﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Linq.Expressions;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;


namespace DEWY_SSIS_CONFIG_MANAGER
{

    public partial class MasterWindow : Form
    {
        //Global Open File Dialog
        OpenFileDialog ofd_ConfigFileOpenDiag;
        //The Current Panel List
        List<Panel> pnlList;
        //The Current Opened Files
        List<FileInfo> OpenedFiles;
        //The Current Active Tab
        String ActiveTabPage = String.Empty;
        //Application Status
        AppStatus appstatus;
        
        public MasterWindow()
        {

            
            OpenedFiles = new List<FileInfo>();
            pnlList = new List<Panel>();

            //Open File Dialogg Properties & Event Handler
            ofd_ConfigFileOpenDiag = new OpenFileDialog();
            ofd_ConfigFileOpenDiag.DefaultExt = "dtsConfig";
            ofd_ConfigFileOpenDiag.Filter = "SSIS Config (*.dtsConfig)|*.dtsConfig|All files (*.*)|*.*";
            ofd_ConfigFileOpenDiag.Multiselect = true;
            ofd_ConfigFileOpenDiag.Title = "Open SSIS Configuration File";
            ofd_ConfigFileOpenDiag.FileOk += new CancelEventHandler(ofd_ConfigFileOpenDiag_FileOk);

            InitializeComponent();

            appstatus = new AppStatus() { MenuVisible = true };

            if (File.Exists(AppDomain.CurrentDomain.BaseDirectory.ToString() + Path.DirectorySeparatorChar + "sts.dt"))
            {
                appstatus.MenuVisible = AppStatus.getStatus();    
            }

            this.menuStrip1.Visible = appstatus.MenuVisible;
        }

        //Data Mode Enum to determine the result type
        private enum DataMode
        {
            All = 1,
            Variables = 2
        }


        void ofd_ConfigFileOpenDiag_FileOk(object sender, CancelEventArgs e)
        {
            try
            {
                String[] strAddedFiles = ofd_ConfigFileOpenDiag.FileNames;
                foreach (string strFile in strAddedFiles)
                {
                    FileInfo file = new FileInfo(strFile);
                    if (OpenedFiles.Exists(exFi => exFi.FullName.Equals(file.FullName)) == false)
                    {
                        OpenedFiles.Add(file);
                        ExtractAndLoadDisplay(file.FullName);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }

 


        private void btn_OpenConfigFile_Click(object sender, EventArgs e)
        {
            ofd_ConfigFileOpenDiag.ShowDialog();
        }

        private void MasterWindow_Load(object sender, EventArgs e)
        {

            

            try
            {
                if (String.IsNullOrEmpty(this.SelectedFile))
                {
                    String AppDir = AppDomain.CurrentDomain.BaseDirectory;
                    DirectoryInfo dinfp = new DirectoryInfo(AppDir);
                    //MessageBox.Show(AppDir);
                    FileInfo[] fis = dinfp.GetFiles("*.dtsconfig", SearchOption.AllDirectories);

                    OpenedFiles.AddRange(fis);

                    if (fis.Length > 0)
                    {
                        this.ClearControls();
                        foreach (FileInfo fi in fis)
                        {
                            //OpenedFiles.Add(fi);
                            ExtractAndLoadDisplay(fi.FullName);
                        }
                        /*
                        pnl_LoadControl.Enabled = false;
                        pnl_LoadControl.Hide();
                        pnl_LoadControl.Size = new Size(0, 0);
                         * */
                    }
                }
                else
                {
                    if (File.Exists(this.SelectedFile))
                    {
                        //MessageBox.Show(this.SelectedFile);
                        OpenedFiles.Add(new FileInfo(this.SelectedFile));
                        ExtractAndLoadDisplay(this.SelectedFile);
                    }

                }
            }
            catch (Exception expOpenein)
            {
                MessageBox.Show(expOpenein.Message);
            }

        }

        private void txtbx_ConfigFilepath_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (e.KeyChar == (char)Keys.Enter)
                {
                    if (File.Exists(txtbx_ConfigFilepath.Text))
                    {
                        this.ClearControls();
                        ExtractAndLoadDisplay(txtbx_ConfigFilepath.Text);
                    }
                    else
                    {
                        MessageBox.Show("File does not exists");
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


        void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                String strfInfo = ((sender as Button).Tag.ToString());
                FileInfo finfo = new FileInfo(strfInfo);
                XDocument xdoc = XDocument.Load(strfInfo);
                //MessageBox.Show(((sender as Button).Parent as Panel).Name.ToString());
                Panel ContrainerPanel = (((sender as Button).Parent as Panel).Parent as Panel);
                foreach (Control ctrl in ContrainerPanel.Controls)
                {
                    if (ctrl is Panel && (ctrl as Panel).Name.Contains("sub_pnl_"))
                    {
                        Panel subPanelMember = ctrl as Panel;
                        EditableItems item = subPanelMember.Tag as EditableItems;
                        String Value = String.Empty;
                        switch (item.Type.ToLower())
                        {
                            case "datetime":
                                Control[] dtp_time;
                                Control[] dtp_hours;
                                DateTime dtDate;
                                String dtTime;


                                dtp_time = subPanelMember.Controls.Find("dtp_" + item.ConfigurableName, false);
                                dtp_hours = subPanelMember.Controls.Find("txtBx_" + item.ConfigurableName, false);


                                dtDate = (dtp_time[0] as DateTimePicker).Value;
                                dtTime = (dtp_hours[0] as TextBox).Text;

                                // Value = (dtp_time[0] is DateTimePicker) ? (dtp_time[0] as DateTimePicker).Text : String.Empty;
                                Value = String.Format("{0} {1}", dtDate.ToString("M/d/yyyy"), dtTime);


                                XElement xelEdutDateTime = (from elm in xdoc.Descendants("Configuration")
                                                            where elm.Attribute("Path").Value.Equals(item.Path)
                                                            select elm).FirstOrDefault();
                                XElement xelEditValueDateTime = (from elval in xelEdutDateTime.Descendants("ConfiguredValue") select elval).FirstOrDefault();
                                xelEditValueDateTime.Value = Value;

                                break;
                            case "boolean":
                                Control[] chkbx_Bool;
                                chkbx_Bool = subPanelMember.Controls.Find("cb_" + item.ConfigurableName, false);

                                Value = (chkbx_Bool[0] is CheckBox) ? ((chkbx_Bool[0] as CheckBox).Checked ? "-1" : "0") : "0";

                                XElement xelEdutBoolean = (from elm in xdoc.Descendants("Configuration")
                                                           where elm.Attribute("Path").Value.Equals(item.Path)
                                                           select elm).FirstOrDefault();
                                XElement xelEditValuebool = (from elval in xelEdutBoolean.Descendants("ConfiguredValue") select elval).FirstOrDefault();
                                xelEditValuebool.Value = Value;

                                break;
                            case "empty":
                                break;
                            default:
                                Control[] txtbx_str;
                                txtbx_str = subPanelMember.Controls.Find("txt_" + item.ConfigurableName, false);

                                Value = (txtbx_str[0] is TextBox) ? (txtbx_str[0] as TextBox).Text : String.Empty;
                                //xdoc.Descendants("Configuration").Where(des => des.Attribute("Path").Value.Equals((subPanelMember.Tag as EditableItems).Path.ToString())).FirstOrDefault().Descendants("ConfiguredValue").FirstOrDefault().Value = Value;



                                XElement xelEdut = (from elm in xdoc.Descendants("Configuration")
                                                    where elm.Attribute("Path").Value.Equals(item.Path)
                                                    select elm).FirstOrDefault();
                                XElement xelEditValue = (from elval in xelEdut.Descendants("ConfiguredValue") select elval).FirstOrDefault();
                                xelEditValue.Value = Value;

                                break;

                        }
                        //xdoc.Descendants("Configuration").Where(des=>des.Attribute("Path").Value.Equals(subPanelMember.Tag.ToString())).Descendants("ConfiguredValue").FirstOrDefault().Value = 
                    }
                }
                xdoc.Save(finfo.FullName);
            }
            catch (Exception x)
            {
                MessageBox.Show(x.Message);
            }
        }

        //ASD helper Methods
        private void ClearControls()
        {
            try
            {
                //this.pnl_DockAllContent.Controls.Clear();
                this.tb_Ctrlwrkspace.TabPages.Clear();
            }
            catch (Exception x) 
			{
                MessageBox.Show(x.Message);
            }
        }


        private void ExtractAndLoadDisplay(String FileName, DataMode dataMode = DataMode.All)
        {
            try
            {
                dataMode = DataMode.Variables;

                if (File.Exists(FileName))
                {
                    IEnumerable<XElement> elmcol;
                    FileInfo finfo = new FileInfo(FileName);
                    XDocument xdoc = XDocument.Load(FileName);

                    if (dataMode == DataMode.All)
                    {
                        elmcol = from xe in xdoc.Descendants("Configuration")
                                 where
                                 xe.Attribute("ConfiguredType").Value.Equals("Property")
                                 //Regex.IsMatch(@xe.Attribute("Path").Value, @"^\\[\w_\s\:\[\]\&\.]*\[Value\]$")
                                 select xe;
                    }
                    else

                    //if (DataMode == DataMode.Variables)
                    {
                        elmcol = from xe in xdoc.Descendants("Configuration")
                                 where
                                     //xe.Attribute("ConfiguredType").Value.Equals("Property")
                                 Regex.IsMatch(@xe.Attribute("Path").Value, @"^\\[\w_\s\:\[\]\&\.]*\[Value\]$")
                                 select xe;
                    }

                    IEnumerable<EditableItems> items2edit = from xl in elmcol
                                                            select new EditableItems
                                                            {
                                                                ConfigurableName =
                                                                (xl.Attribute("Path").Value.Contains("Properties[Value]") && xl.Attribute("Path").Value.Contains("Variables["))
                                                                ?
                                                                xl.Attribute("Path").Value.Replace(@"\Package.Variables[", "").Replace(@"].Properties[Value]", "").Trim()
                                                                :
                                                                 (xl.Attribute("Path").Value.Contains("Package.Properties"))
                                                                 ?
                                                                 xl.Attribute("Path").Value.Replace(@"\Package.Properties[", "").TrimEnd(new char[] { ']' })
                                                                 :
                                                                  (xl.Attribute("Path").Value.Contains("Properties[") && xl.Attribute("Path").Value.Contains("Variables["))
                                                                  ?
                                                                  xl.Attribute("Path").Value.Replace(@"\Package.Variables[", "").Replace(@"].Properties[", " (").TrimEnd(new char[] { ']' }) + ")"
                                                                  :
                                                                    (xl.Attribute("Path").Value.Contains("Package.Connections"))
                                                                    ?
                                                                     xl.Attribute("Path").Value.Replace(@"\Package.Connections", "(Connection)").Replace(@"].Properties[", "(").TrimEnd(new char[] { ']' }) + ")"
                                                                    :
                                                                     xl.Attribute("Path").Value
                                                                ,
                                                                Path = xl.Attribute("Path").Value,
                                                                Type = xl.Attribute("ValueType").Value,
                                                                Value = xl.Descendants("ConfiguredValue").FirstOrDefault().Value,
                                                                Description = FindDescr(xdoc, xl.Attribute("Path").Value)
                                                            };


                    pnlList = (from item in items2edit select item.UI()).ToList();

                    //MessageBox.Show(pnlList.Count.ToString());
                    //MessageBox.Show(elmcol.Count().ToString());
                    // bs_DataSrcXMLEdit.DataSource = items2edit;
                    //editableItemsDataGridView.DataSource = bs_DataSrcXMLEdit;

                    TabPage tbPage = new TabPage();
                    tbPage.ToolTipText = finfo.Name;
                    tbPage.Text = finfo.Name;
                    tbPage.AutoScroll = true;
                    tbPage.Name = "tbPage_" + finfo.FullName;




                    Panel pnlMainContrainerPanel = new Panel();
                    pnlMainContrainerPanel.Dock = DockStyle.Fill;
                    pnlMainContrainerPanel.AutoScroll = true;
                    pnlMainContrainerPanel.Name = "pnlMainContrainerPanel" + finfo.Name;

                    foreach (Panel pnl in pnlList)
                    {
                        
                        pnlMainContrainerPanel.Controls.Add(pnl);

                    }


                    Panel pnlBtnPanel = new Panel()
                    {
                        Name = "btnPanel_" + finfo.Name,
                        Dock = DockStyle.Bottom,
                        Height = 50
                    };

                    Button btnSave = new Button()
                    {
                        Name = "btnSave_" + finfo.Name,
                        Tag = finfo.FullName,
                        Width = 200,
                        Height = 40,
                        // Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.None))),
                        Dock = DockStyle.Right,
                        Text = String.Format("Save {0}!", finfo.Name)
                    };


                    btnSave.Click += new EventHandler(btnSave_Click);
                    pnlBtnPanel.Controls.Add(btnSave);


                    pnlMainContrainerPanel.Controls.Add(pnlBtnPanel);




                    tbPage.Controls.Add(pnlMainContrainerPanel);

                    tb_Ctrlwrkspace.TabPages.Add(tbPage);
                    tb_Ctrlwrkspace.SelectedTab = tbPage;
                    this.ActiveTabPage = tbPage.Name;
                }
                else
                {
                    MessageBox.Show("File does not exists");
                }
            }
            catch (Exception x)
            {
                MessageBox.Show(x.Message);
            }
        }

        private string FindDescr(XDocument xdoc, string name)
        {
            IEnumerable<string> temp =
                from xe in xdoc.Descendants("Configuration")
                where @xe.Attribute("Path").Value.Contains(name.Replace("[Value]", "[Description]"))
                select xe.Elements("ConfiguredValue").First().Value;
            return temp.Count() == 0 ? null : temp.First();

            //xdoc.Descendants("Configuration").Elements(xl.Attribute("Path").Value.Replace("[Value]", "[Description]")).First().Elements().First().Value.ToString()
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                String EnvVar = Microsoft.VisualBasic.Interaction.InputBox("Enter Environment Variable Name", "Environment Variable", "Environment Variable");
                if (!String.IsNullOrEmpty(EnvVar))
                {
                    String strFileNameEnv = System.Environment.GetEnvironmentVariable(EnvVar, EnvironmentVariableTarget.Machine);
                    if (File.Exists(strFileNameEnv))
                    {
                        if (!OpenedFiles.Exists(fi => fi.FullName.Equals(strFileNameEnv)))
                        {
                            OpenedFiles.Add(new FileInfo(strFileNameEnv));
                            ExtractAndLoadDisplay(strFileNameEnv, DataMode.All);
                        }
                        else
                        {
                            this.tb_Ctrlwrkspace.SelectedTab = this.tb_Ctrlwrkspace.TabPages["tbPage_" + strFileNameEnv];
                        }
                    }
                    else
                    {
                        MessageBox.Show("The Environment Variable does not correctly point to a configuration file");
                    }
                }
            }
            catch (Exception x)
            {
                MessageBox.Show(x.Message);
            }

        }



            private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
            {
                try
                {
                    AboutBox b = new AboutBox();
                    b.ShowDialog();
                }
                catch
                {
                    MessageBox.Show("Ahmed Dewedar (ahmed@dewedar.com)");
                }
            }


            private void exitToolStripMenuItem_Click(object sender, EventArgs e)
            {
                Application.Exit();
            }

            private void helpToolStripMenuItem_Click(object sender, EventArgs e)
            {
                ProcessStartInfo proinfo = new ProcessStartInfo("http://ssisconfiguration.codeplex.com/");
                Process.Start(proinfo);
            }

    }

    [Serializable]
    public class AppStatus
    {

        public bool MenuVisible { get; set; }

        
        public AppStatus()
        {
        }

        
        public static bool getStatus()
        {
            try
            {
                FileStream fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory.ToString()+"sts.dt" , FileMode.OpenOrCreate);
                //StreamReader sr = new StreamReader(AppDomain.CurrentDomain.BaseDirectory.ToString() + "sts.dt");
                
                fs.Position = 0;
                
                BinaryFormatter bf = new BinaryFormatter();

                AppStatus app2 = (AppStatus)bf.Deserialize(fs);
                fs.Close();
                return app2.MenuVisible;

            }
            catch 
            {
                return false;
            }
        }
        
        public static void CreateStatus(AppStatus app)
        {
            try
            {
                FileStream fs =
                    new FileStream(AppDomain.CurrentDomain.BaseDirectory.ToString() + Path.DirectorySeparatorChar + "sts.dt", FileMode.OpenOrCreate);
                fs.Position = 0;
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, app);
                fs.Close();
            }
            catch 
            {
                
            }
        }
    }
}
